package com.jiangxjsy.core.jwt;

import com.jiangxjsy.core.annotation.JwtPayloadKey;
import io.jsonwebtoken.Claims;
import io.jsonwebtoken.Jws;
import io.jsonwebtoken.Jwts;
import io.jsonwebtoken.SignatureAlgorithm;
import org.joda.time.DateTime;

import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.security.PrivateKey;
import java.security.PublicKey;
import java.util.HashMap;
import java.util.Map;

/**
 * wukong-crm-master
 * 蒋胜宇
 * 2025/5/29 16:15
 */

public class JwtCore<T> {
    private final Class<T> payloadClazz;

    public JwtCore(Class<T> payloadClazz) {
        this.payloadClazz = payloadClazz;
    }

    /**
     * 生成 token
     *
     * @param payload 负载
     * @param privateKey 私钥
     * @param expires 有效期，单位：分钟
     * @return token
     */
    public String generateToken(T payload, PrivateKey privateKey, int expires) throws IllegalAccessException {
        Map<String, Object> claims = new HashMap<>();
        for (Field field : payloadClazz.getDeclaredFields()) {
            field.setAccessible(true);
            String key;
            try {
                key = field.getAnnotation(JwtPayloadKey.class).value();
            } catch (NullPointerException ignore) {
                continue;
            }
            claims.put(key, field.get(payload));
        }

        return Jwts.builder()
                .setClaims(claims)
                .setExpiration(DateTime.now().plusMinutes(expires).toDate())
                .signWith(SignatureAlgorithm.RS384, privateKey)
                .compact();
    }

    /**
     * 解析 token
     *
     * @param token token
     * @param publicKey 公钥
     * @return 负载
     */
    public T analyzeToken(String token, PublicKey publicKey) throws IllegalAccessException, NoSuchMethodException, InvocationTargetException, InstantiationException {
        Jws<Claims> claimsJws = Jwts.parser().setSigningKey(publicKey).parseClaimsJws(token);
        Claims claims = claimsJws.getBody();

        T payload = payloadClazz.getDeclaredConstructor().newInstance();
        for (Field field : payloadClazz.getDeclaredFields()) {
            field.setAccessible(true);
            String key;
            try {
                key = field.getAnnotation(JwtPayloadKey.class).value();
            } catch (NullPointerException ignore) {
                continue;
            }
            field.set(payload, claims.get(key, field.getType()));
        }

        return payload;
    }
}
